home *** CD-ROM | disk | FTP | other *** search
- Newsgroups: comp.lang.c
- Path: nntp.coast.net!torn!sq!msb
- From: msb@sq.com (Mark Brader)
- Subject: Re: Extracting chars from shorts.
- Message-ID: <1996Jan10.202721.5216@sq.com>
- Organization: SoftQuad Inc., Toronto, Canada
- References: <4d13i0$k3s@lastactionhero.rs.itd.umich.edu>
- Date: Wed, 10 Jan 1996 20:27:21 GMT
-
- Tom Spindler (dogcow@monet.ccs.itd.umich.edu) writes:
- > I'm trying to extracts individual bytes from a double.
-
- Apparently he means "from an unsigned short".
-
- > The following code doesn't work:
- > typedef unsigned char zbyte; /* unsigned 1 byte quantity */
- > typedef unsigned short zword; /* unsigned 2 byte quantity */
- >
- > typedef union zw_u_t {
- > zword zword;
- > struct {zbyte hi,lo;} zbyte;
- > } zwordun;
-
- That's okay, given that the endianness and the type sizes are known.
- Personally I'd rather use an array for the zbyte member, as this
- clearly expresses the fact that the bytes are to be contiguous.
-
- > #define lo(v) ((zbyte) (((zwordun) v).zbyte.lo))
- > #define hi(v) ((zbyte) (((zwordun) v).zbyte.hi))
- > ...
- > One compiler complains that it's an illegal cast, whereas gcc says that the
-
- No other type can be converted to a union type in standard C, because
- the compiler would have to guess which member of the union to assign to.
- Instead of zfoo = lo(foon), write it with a temporary variable:
-
- zwordun ztemp;
- ztemp.zword = foon;
- zfoo = ztemp.zbyte.lo;
-
- Having seen this, it's tempting to say
-
- zwordun ztemp; /* global for lo and hi macros */
- #define lo(v) (ztemp.zword = (v), ztemp.zbyte.lo) /* POOR */
- #define hi(v) (ztemp.zword = (v), ztemp.zbyte.hi) /* POOR */
-
- but this causes undefined behavior if you use two of these expressions
- without a sequence point intervening, as in
-
- printf ("hi byte %d, lo byte %d\n", hi(x), lo(x)); /* WRONG */
-
- And there is no way to fix this in an expression-like macro. (The comma
- operators do introduce two sequence points, but you need a third one and
- there's no way to get it.)
-
- Just like the case of swapping two values, using a union this way is
- something that is better NOT done with a macro in C.
-
-
- But why use a union? If unsigned short is known to be 2 bytes, then
- all you need is
-
- #include <limits.h>
- #define hi(v) ((v) >> CHAR_BIT)
- #define lo(v) ((v) & UCHAR_MAX)
-
- The opposite transformation is also easily accomplished with bitwise
- operations.
- --
- Mark Brader, msb@sq.com, SoftQuad Inc., Toronto
- #define MSB(type) (~(((unsigned type)-1)>>1))
-
- My text in this article is in the public domain.
-